

#ifndef UC_GEMAT2D_H
#define UC_GEMAT2D_H

#include "zgegbl.h"
#include "zgepnt2d.h"
#pragma pack (push, 8)

class UcGeVector2d;
class UcGeLine2d;
class UcGeTol;

class 
GE_DLLEXPIMPORT
UcGeMatrix2d
{
public:
    UcGeMatrix2d();
    UcGeMatrix2d(const UcGeMatrix2d& src);

    static const   UcGeMatrix2d   kIdentity;

    UcGeMatrix2d&  setToIdentity();

    UcGeMatrix2d   operator *   (const UcGeMatrix2d& mat) const;
    UcGeMatrix2d&  operator *=  (const UcGeMatrix2d& mat);
    UcGeMatrix2d&  preMultBy    (const UcGeMatrix2d& leftSide);
    UcGeMatrix2d&  postMultBy   (const UcGeMatrix2d& rightSide);
    UcGeMatrix2d&  setToProduct (const UcGeMatrix2d& mat1, const UcGeMatrix2d& mat2);

    UcGeMatrix2d&  invert       ();
    UcGeMatrix2d   inverse      () const;

    ZSoft::Boolean isSingular   (const UcGeTol& tol = UcGeContext::gTol) const;

    UcGeMatrix2d&  transposeIt  ();
    UcGeMatrix2d   transpose    () const;

    bool operator ==  (const UcGeMatrix2d& mat) const;
    bool operator !=  (const UcGeMatrix2d& mat) const;
    bool isEqualTo    (const UcGeMatrix2d& mat,
                       const UcGeTol& tol = UcGeContext::gTol) const;

    ZSoft::Boolean isUniScaledOrtho(const UcGeTol& tol = UcGeContext::gTol) const;
    ZSoft::Boolean isScaledOrtho(const UcGeTol& tol = UcGeContext::gTol) const;
	double		   scale(void);

    double         det          () const;

    UcGeMatrix2d&  setTranslation(const UcGeVector2d& vec);
    UcGeVector2d   translation  () const;

    ZSoft::Boolean isConformal (double& scale, double& angle,
                                ZSoft::Boolean& isMirror, UcGeVector2d& reflex) const;

    UcGeMatrix2d&  setCoordSystem(const UcGePoint2d& origin,
                                 const UcGeVector2d& e0,
                                 const UcGeVector2d& e1);
    void           getCoordSystem(UcGePoint2d& origin,
                                 UcGeVector2d& e0,
                                 UcGeVector2d& e1) const;

    UcGeMatrix2d& setToTranslation(const UcGeVector2d& vec);
    UcGeMatrix2d& setToRotation (double angle,
                                 const UcGePoint2d& center
				 = UcGePoint2d::kOrigin);
    UcGeMatrix2d& setToScaling  (double scaleAll,
                                 const UcGePoint2d& center
				 = UcGePoint2d::kOrigin);
    UcGeMatrix2d& setToMirroring(const UcGePoint2d& pnt);
    UcGeMatrix2d& setToMirroring(const UcGeLine2d& line);
    UcGeMatrix2d& setToAlignCoordSys(const UcGePoint2d&  fromOrigin,
                                 const UcGeVector2d& fromE0,
                                 const UcGeVector2d& fromE1,
                                 const UcGePoint2d&  toOrigin,
                                 const UcGeVector2d& toE0,
                                 const UcGeVector2d& toE1);

    static
    UcGeMatrix2d translation    (const UcGeVector2d& vec);
    static
    UcGeMatrix2d rotation       (double angle, const UcGePoint2d& center
				 = UcGePoint2d::kOrigin);
    static
    UcGeMatrix2d scaling        (double scaleAll, const UcGePoint2d& center
				 = UcGePoint2d::kOrigin);
    static
    UcGeMatrix2d mirroring      (const UcGePoint2d& pnt);
    static
    UcGeMatrix2d mirroring      (const UcGeLine2d& line);
    static
    UcGeMatrix2d alignCoordSys  (const UcGePoint2d& fromOrigin,
                                 const UcGeVector2d& fromE0,
                                 const UcGeVector2d& fromE1,
                                 const UcGePoint2d&  toOrigin,
                                 const UcGeVector2d& toE0,
                                 const UcGeVector2d& toE1);

    double         operator ()  (unsigned int, unsigned int) const;
    double&        operator ()  (unsigned int, unsigned int);

    double         entry[3][3]; 
};

ZSOFT_FORCE_INLINE bool
UcGeMatrix2d::operator == (const UcGeMatrix2d& otherMatrix) const
{
    return this->isEqualTo(otherMatrix);
}

ZSOFT_FORCE_INLINE bool
UcGeMatrix2d::operator != (const UcGeMatrix2d& otherMatrix) const
{
    return !this->isEqualTo(otherMatrix);
}

ZSOFT_FORCE_INLINE double
UcGeMatrix2d::operator () (
    unsigned int row,
    unsigned int column) const
{
    return entry[row][column];
}

ZSOFT_FORCE_INLINE double&
UcGeMatrix2d::operator () (
    unsigned int row,
    unsigned int column)
{
    return entry[row][column];
}

#pragma pack (pop)
#endif
